/*
 * =====================================================================================
 *
 *       Filename:  brutal.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  21.4.2013 16:20:31
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  YOUR NAME (), 
 *   Organization:  
 *
 * =====================================================================================
 */

#include <linux/module.h>
#include <linux/kernel.h>

#include <linux/sched.h>

#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>

#define TRUE  1
#define FALSE 0

#define START_ADDR  0xc0000000
#define END_ADDR    0xffffffff

#define MAX_PID 32768

#define STARTLEN    40
#define INCREASELEN 20

struct task_struct **discoveredTasks;
int discoveredCount;


MODULE_LICENSE("GPL");
MODULE_AUTHOR("Radek Necas");
MODULE_DESCRIPTION("Get all proceses in task list");


int isTask(const struct task_struct *task) 
{
    int id;
    long state;

    state = task->state;
    if((state != TASK_RUNNING) && (state != TASK_INTERRUPTIBLE) && (state != TASK_UNINTERRUPTIBLE) 
            && (state != __TASK_STOPPED) && (state != __TASK_TRACED)) {
        return FALSE;
    }
    else {
        printk(KERN_INFO "state = %ld", state);
    }

    id = task->pid;
    if(id <= 0 || id > MAX_PID)
        return FALSE; 

    id = task->tgid;
    if(id <= 0 || id > MAX_PID)
        return FALSE;
/*  
    if(task->real_parent > END_ADDR || task->real_parent < START_ADDR)
        return FALSE;

    if(task->parent > END_ADDR || task->parent < START_ADDR)
        return FALSE;
*/
    return TRUE;
}


int taskListMemory(void)
{
    const struct task_struct *taskPtr;
    unsigned long ptr;

    int taskStructSize;
    int arrayLen;
    long taskPtrSize;

    arrayLen = STARTLEN;
    taskPtrSize = sizeof(struct task_struct *);
    taskStructSize = sizeof(struct task_struct);

    discoveredTasks = (struct task_struct **)kmalloc(arrayLen*taskPtrSize, GFP_KERNEL);
    if(discoveredTasks == NULL) {
        printk(KERN_INFO "memorySearch: Chyba pri alokaci pameti");
        printk(KERN_INFO "");
        return -1;
    }


    printk(KERN_INFO "brutalForce: volana taskListMemory()");
    printk(KERN_INFO "");

    //memset(discoveredTasks, NULL, sizeof(discoveredTasks));
    discoveredCount = 0;


    //ptr = END_ADDR - taskStructSize;
    ptr = START_ADDR;
    //while(ptr >= START_ADDR) {
    while(ptr < (END_ADDR - taskStructSize)) {
        taskPtr = (struct task_struct *)ptr;

        //printk(KERN_INFO "brutalForce: prohledavam adresu: %p", ptr);
        if(!isTask(taskPtr)) {
            goto NEXT;
        }
        
        if(discoveredCount >= arrayLen) {
            arrayLen += INCREASELEN;
            discoveredTasks = (struct task_struct **)krealloc(discoveredTasks, arrayLen*taskPtrSize, GFP_KERNEL);
            if(discoveredTasks == NULL) {
                printk(KERN_INFO "memorySearch: Chyba pri realokaci pameti \n");
                kfree(discoveredTasks);
                return -1;
            }
        }

        if(discoveredCount <= MAX_PID) {
            //printk(KERN_INFO "brutalForce: pridava se proces %s[%d]", taskPtr->comm, taskPtr->pid);
            //printk(KERN_INFO "");
            discoveredTasks[discoveredCount] = taskPtr;
            discoveredCount++;
        }
        else {
            printk(KERN_INFO "brutalForce: Odhaleno prilis mnoho procesu");
            printk(KERN_INFO "");
            break;
        }

NEXT:
        //ptr -= sizeof(void *);
        ptr += sizeof(void *);
    }

    printk(KERN_INFO "Naslo se %d procesu", discoveredCount);
    printk(KERN_INFO "");

    return discoveredCount;
}


int init_module(void)
{
    //struct task_struct *task;
    printk(KERN_INFO "brutalForce: modul zaveden");
    printk(KERN_INFO "");

/*
    for_each_process(task) {
        printk(KERN_INFO "Adresa procesu: %p", (void *)task);
        printk(KERN_INFO "");
    }
*/
    taskListMemory();

    return 0;
}

void cleanup_module(void)
{
    printk(KERN_INFO "brutalForce: modul odebran");
    printk(KERN_INFO "");

}
